#include "CameraClass.h"

CameraClass::CameraClass(void)
	:Component(COMP_CAMERA),
	m_FarPlane(0.0f),
	m_NearPlane(0.0f),
	m_AspectRadio(0.0f),
	m_position(XMLoadFloat3(&XMFLOAT3(0.0f,0.0f,-100.0f))),
	m_up(XMLoadFloat3(&XMFLOAT3(0.0f,1.0f,0.0f))),
	m_target(XMLoadFloat3(&XMFLOAT3(0.0f,0.0f,1.0f))),
	m_ViewMatrix(XMMatrixIdentity()),
	m_PerspectiveMatrix(XMMatrixIdentity()),
	m_OrthoMatrix(XMMatrixIdentity()),
	m_screenWidth(0),
	m_screenHeight(0)
{
}

CameraClass::~CameraClass(void)
{
}

void CameraClass::AddedToObject()
{
	RequestMessage(MSG_INITIAL,&CameraClass::Initial);
	RequestMessage(MSG_GET_VIEW_MATRIX,&CameraClass::GetViewMatrix);
	RequestMessage(MSG_GET_PERSP_MATRIX,&CameraClass::GetPerspectiveMatrix);
	RequestMessage(MSG_CAMERA_UP,&CameraClass::MoveUp);
	RequestMessage(MSG_CAMERA_DOWN,&CameraClass::MoveDown);
	RequestMessage(MSG_CAMERA_LEFT,&CameraClass::MoveLeft);
	RequestMessage(MSG_CAMERA_RIGHT,&CameraClass::MoveRight);
	RequestMessage(MSG_CAMERA_RLEFT,&CameraClass::RoundLeft);
	RequestMessage(MSG_CAMERA_RRIGHT,&CameraClass::RoundRight);
	RequestMessage(MSG_CAMERA_IN,&CameraClass::MoveIn);
	RequestMessage(MSG_CAMERA_OUT,&CameraClass::MoveOut);
}

void CameraClass::Initial(const Message& msg)
{
	HINSTANCE hInstance;
	HWND hWnd;
	AuxUnGroupArgus(msg.p,hInstance,hWnd,m_screenWidth,m_screenHeight);

	m_FarPlane=10000.0f;
	m_NearPlane=1.0f;
	m_AspectRadio=m_screenWidth/m_screenHeight;
	m_ViewMatrix=XMMatrixLookAtLH(m_position,m_target,m_up);
	m_PerspectiveMatrix=XMMatrixPerspectiveFovLH(XM_PIDIV4,m_AspectRadio,m_NearPlane,m_FarPlane);
	m_OrthoMatrix=XMMatrixOrthographicLH(m_screenWidth,m_screenHeight,m_NearPlane,m_FarPlane);
}

void CameraClass::MoveUp(const Message& msg)
{
	XMFLOAT3 tmpOriant(0.0f,1.0f,0.0f);
	XMVECTOR oriantation=XMLoadFloat3(&tmpOriant);
	m_position+=oriantation;
	m_target+=oriantation;
}

void CameraClass::MoveDown(const Message& msg)
{
	XMFLOAT3 tmpOriant(0.0f,-1.0f,0.0f);
	XMVECTOR oriantation=XMLoadFloat3(&tmpOriant);
	m_position+=oriantation;
	m_target+=oriantation;
}

void CameraClass::MoveLeft(const Message& msg)
{
	XMVECTOR tmp=m_target-m_position;
	XMVECTOR oriantation=XMVector3Cross(tmp,m_up);
	m_position+=oriantation;
	m_target+=oriantation;
}

void CameraClass::MoveRight(const Message& msg)
{
	XMVECTOR tmp=m_target-m_position;
	XMVECTOR oriantation=XMVector3Cross(tmp,m_up);
	m_position-=oriantation;
	m_target-=oriantation;
}

void CameraClass::MoveIn(const Message& msg)
{
	XMVECTOR oriantation=m_target-m_position;
	oriantation=XMVector3Normalize(oriantation);
	m_position+=oriantation;
	m_target+=oriantation;
}

void CameraClass::MoveOut(const Message& msg)
{
	XMVECTOR oriantation=m_target-m_position;
	oriantation=XMVector3Normalize(oriantation);
	m_position-=oriantation;
	m_target-=oriantation;
}

void CameraClass::RoundLeft(const Message& msg)
{
	XMVECTOR tmp=m_target-m_position;
	tmp=XMVector3Transform(tmp,XMMatrixRotationY(-0.1f));
	m_target=m_position+tmp;
}

void CameraClass::RoundRight(const Message& msg)
{
	XMVECTOR tmp=m_target-m_position;
	tmp=XMVector3Transform(tmp,XMMatrixRotationY(0.1f));
	m_target=m_position+tmp;
}

void CameraClass::SetPosition(float x, float y, float z)
{
	m_position=XMLoadFloat3(&XMFLOAT3(x,y,z));
}

void CameraClass::GetViewMatrix(const Message& msg)
{
	XMMATRIX* viewMatrix=NULL;
	AuxUnGroupArgus(msg.p,viewMatrix);
	_update();
	*viewMatrix=m_ViewMatrix;
}

const XMMATRIX& CameraClass::GetViewMatrix()
{
	_update();
	return m_ViewMatrix;
}

void CameraClass::GetPerspectiveMatrix(const Message& msg)
{
	XMMATRIX* perspectiveMatrix=NULL;
	AuxUnGroupArgus(msg.p,perspectiveMatrix);
	*perspectiveMatrix=m_PerspectiveMatrix;
}

const XMMATRIX& CameraClass::GetPerspectiveMatrix()
{
	return m_PerspectiveMatrix;
}

const XMMATRIX& CameraClass::GetOrthoMatrix()
{
	return m_OrthoMatrix;
}

void CameraClass::_update()
{
	m_ViewMatrix=XMMatrixLookAtLH(m_position,m_target,m_up);
}